

import files.Files;
import function.Mp3File;
import graphics.SearchChoiceInput;

import java.io.IOException;
import java.util.Calendar;
import java.util.Random;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;

import state.State;
import tool.KeyCode;
import tool.Properties;
import boot.Boot;
import db.DBListener;
import db.DBReader;
import db.Mp3DBRecord;

public class SuggestScreen extends Canvas implements CommandListener {

	private static final int PREFETCH_CAPACITY = 3;

	private final Command cancelCommand = new Command("Cancel", Command.EXIT, 1);

	SearchChoiceInput mp3ListDisplay;
	// Matrix of mp3s
	private Mp3File[][] mp3Matrix;
	Mp3File[] mp3s;
	// Indixes for random search
	int[] indixes;
	// DB reader
	DBReader dbReader;

	private int prefetchCount;

	private boolean isPrefetchRunning;

	public SuggestScreen() {
		mp3Matrix = new Mp3File[PREFETCH_CAPACITY][];
		prefetchCount = 0;
		isPrefetchRunning = false;
		new Thread(new Runnable() {

			public void run() {
				chooseRandomMp3s();
				mp3Matrix[0] = mp3s;
				prefetchCount++;
				showMp3andPrefetch();
			}

		}).start();
	}

	private void detachedPrefetch() {
		new Thread(new Runnable() {

			public void run() {
				prefetch();
			}
		}).start();
	}

	private void prefetch() {
		if (isPrefetchRunning) {
			return;
		}

		isPrefetchRunning = true;
		while (prefetchCount < PREFETCH_CAPACITY) {
			chooseRandomMp3s();
			mp3Matrix[prefetchCount] = mp3s;
			prefetchCount++;
		}
		isPrefetchRunning = false;
	}

	private void chooseRandomMp3s() {
		int numMp3 = 7;
		indixes = new int[numMp3];
		mp3s = new Mp3File[numMp3];

		String dbPropertiesPath = null;

		if (Boot.state().equals(State.WICKED_KEY_PRESSED)) {
			dbPropertiesPath = Files.BOOT_ROOT
					+ "/DBProperties/NoPoubelle.db.properties";
			dbReader = new DBReader(Files.BOOT_ROOT + "/NoPoubelle.db");
		} else {
			dbPropertiesPath = Files.BOOT_ROOT
					+ "/DBProperties/Boot.db.properties";
			dbReader = new DBReader(Files.BOOT_ROOT + "/Boot.db");
		}

		Properties props = new Properties(dbPropertiesPath);
		int size = Integer.parseInt(props.getProperty("num"));

		for (int i = 0; i < numMp3; i++) {
			int nextInt = getNewRandomValue(size);

			while (indexesContains(nextInt, i)) {
				nextInt = getNewRandomValue(size);
			}

			if (i == 0) {
				indixes[0] = nextInt;
			} else {
				int current = i;

				while ((current != 0) && (indixes[current - 1] > nextInt)) {
					indixes[current] = indixes[current - 1];
					current--;
				}
				indixes[current] = nextInt;
			}
		}

		dbReader.addListener(new SuggestListener());
		dbReader.readDB();
	}

	private boolean indexesContains(int nextInt, int index) {
		boolean result = false;
		for (int j = 0; (j < index) && !result; j++) {
			result = (indixes[j] == nextInt);
		}
		return result;
	}

	private int getNewRandomValue(int max) {
		return new Random(Calendar.getInstance().getTime().getTime())
				.nextInt(max);
	}

	protected void paint(Graphics g) {
		addCommand(cancelCommand);
		setCommandListener(this);
		if (mp3ListDisplay != null) {
			mp3ListDisplay.repaint(g);
		}
	}

	public void keyPressed(int keyCode) {
		if ((keyCode == KeyCode.HAUT) || (keyCode == KeyCode.BAS)
				|| (keyCode == KeyCode.GAUCHE) || (keyCode == KeyCode.DROITE)
				|| (keyCode == KeyCode.DIESE)) {
			if (prefetchCount > 0) {
				showMp3andPrefetch();
			} else {
				detachedPrefetch();
			}
		} else {
			mp3ListDisplay.processKey(keyCode);
			repaint();
		}
	}

	public void commandAction(Command command, Displayable dis) {
		if (command == cancelCommand) {
			Boot.getInstance().readyToGo();
		}
	}

	private class SuggestListener implements DBListener {

		// What is current record index ?
		int recordIndex = 0;
		// What poistion in arrays a we ?
		int currentPos = 0;

		public void processRecord(Mp3DBRecord record) {
			recordIndex++;

			if (recordIndex == indixes[currentPos]) {
				mp3s[currentPos] = record.getMp3File();
				currentPos++;
			}
			if (currentPos > indixes.length - 1) {
				try {
					dbReader.stopReading();
				} catch (IOException e) {
					Boot.alert(e);
				}
			}
		}

		public void readingDone() {
			// Do nothing
		}
	}

	private void shiftArray() {
		for (int i = 0; i < PREFETCH_CAPACITY - 1; i++) {
			mp3Matrix[i] = mp3Matrix[i + 1];
		}
		mp3Matrix[PREFETCH_CAPACITY - 1] = new Mp3File[] {};
	}

	private void showMp3andPrefetch() {
		mp3ListDisplay = new SearchChoiceInput(mp3Matrix[0]);
		repaint();
		shiftArray();
		prefetchCount--;
		detachedPrefetch();
	}
}
